/*
 * Copyright (C) 2022-2025 Thomas Akehurst
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.github.tomakehurst.wiremock.db.service;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder;
import com.github.tomakehurst.wiremock.common.Timing;
import com.github.tomakehurst.wiremock.db.entity.WireMockJournal;
import com.github.tomakehurst.wiremock.db.entity.WireMockJournalDetails;
import com.github.tomakehurst.wiremock.db.mapper.WireMockJournalMapper;
import com.github.tomakehurst.wiremock.db.utils.MyBatisUtil;
import com.github.tomakehurst.wiremock.extension.Parameters;
import com.github.tomakehurst.wiremock.http.*;
import com.github.tomakehurst.wiremock.common.Encoding;
import com.github.tomakehurst.wiremock.common.url.PathParams;
import com.github.tomakehurst.wiremock.store.RequestJournalStore;
import com.github.tomakehurst.wiremock.stubbing.ServeEvent;
import com.github.tomakehurst.wiremock.stubbing.StubMapping;
import com.github.tomakehurst.wiremock.stubbing.SubEvent;
import com.github.tomakehurst.wiremock.verification.LoggedRequest;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Stopwatch;
import org.apache.ibatis.session.SqlSession;
import org.wiremock.annotations.Beta;

import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Beta(justification = "Externalized State API: https://github.com/wiremock/wiremock/issues/2144")
public class DbRequestJournalStore implements RequestJournalStore {

    // 依赖：MyBatis Mapper（操作数据库）
//    private final WireMockJournalMapper journalMapper;
    // 依赖：Jackson（序列化/反序列化复杂字段）
    private final ObjectMapper objectMapper = new ObjectMapper();

    // 初始化：通过 MyBatisUtil 获取 Mapper
    public DbRequestJournalStore() {
//        try (SqlSession session = MyBatisUtil.getSqlSession()) {
//            this.journalMapper = session.getMapper(WireMockJournalMapper.class);
//        }
    }

    // ------------------------------
    // 接口方法实现（完整覆盖 RequestJournalStore）
    // ------------------------------

    /**
     * 新增日志：插入主表+详情表（事务控制）
     */
    @Override
    public void add(ServeEvent event) {
        try (SqlSession session = MyBatisUtil.getSqlSession(false)) {
            WireMockJournalMapper sessionMapper = session.getMapper(WireMockJournalMapper.class);

            // 1. ServeEvent → 主表实体
            WireMockJournal journal = convertToJournal(event);
            // 2. ServeEvent → 详情表实体
            WireMockJournalDetails details = convertToJournalDetails(event, journal.getId());

            // 3. 事务内执行插入
            sessionMapper.insertJournal(journal);
            sessionMapper.insertJournalDetails(details);
            session.commit();
        } catch (Exception e) {
            throw new RuntimeException("Failed to add ServeEvent to DB", e);
        }
    }

    /**
     * 查询所有日志：从数据库读取并转换为 ServeEvent 流
     */
    @Override
    public Stream<ServeEvent> getAll() {
        try (SqlSession session = MyBatisUtil.getSqlSession(true)) {
            WireMockJournalMapper sessionMapper = session.getMapper(WireMockJournalMapper.class);
            List<WireMockJournal> journalList = sessionMapper.selectAllJournals();

            // 关键修改：用 collect() 触发 Stream 立即执行，在 session 关闭前完成所有数据库操作
            List<ServeEvent> serveEvents = journalList.stream()
                    .map(journal -> {
                        // 此时 session 仍未关闭，可正常执行查询
                        WireMockJournalDetails details = sessionMapper.selectJournalDetailsByJournalId(journal.getId());
                        return convertToServeEvent(journal, details);
                    })
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList()); // 即时收集结果到 List

            // 返回 List 的 Stream（此时数据已加载完成，session 可安全关闭）
            return serveEvents.stream();
        } catch (Exception e) {
            throw new RuntimeException("Failed to get all ServeEvents from DB", e);
        }
    }

    /**
     * 删除最旧日志：按创建时间删除最早记录
     */
    @Override
    public void removeLast() {
        try (SqlSession session = MyBatisUtil.getSqlSession(false)) {
            WireMockJournalMapper sessionMapper = session.getMapper(WireMockJournalMapper.class);

            // 1. 查询最旧日志ID（按创建时间升序）
            String oldestId = sessionMapper.selectOldestJournalId();
            if (oldestId == null) return;

            // 2. 先删详情表（外键约束），再删主表
            sessionMapper.deleteJournalDetailsByJournalId(oldestId);
            sessionMapper.deleteJournalById(oldestId);
            session.commit();
        } catch (Exception e) {
            throw new RuntimeException("Failed to remove last ServeEvent from DB", e);
        }
    }

    /**
     * 查询所有日志ID
     */
    @Override
    public Stream<UUID> getAllKeys() {
        return getAll().map(ServeEvent::getId);
    }

    /**
     * 按ID查询日志：关联主表+详情表
     */
    @Override
    public Optional<ServeEvent> get(UUID id) {
        try (SqlSession session = MyBatisUtil.getSqlSession(true)) {
            WireMockJournalMapper sessionMapper = session.getMapper(WireMockJournalMapper.class);
            WireMockJournal journal = sessionMapper.selectJournalWithDetails(id.toString());

            if (journal == null) return Optional.empty();
            // 提取关联的详情表数据（若未自动关联，手动查询）
            WireMockJournalDetails details = journal.getDetails() != null
                    ? journal.getDetails()
                    : sessionMapper.selectJournalDetailsByJournalId(journal.getId());

            return Optional.ofNullable(convertToServeEvent(journal, details));
        } catch (Exception e) {
            throw new RuntimeException("Failed to get ServeEvent by ID: " + id, e);
        }
    }

    /**
     * 更新日志：仅更新已存在的记录
     */
    @Override
    public void put(UUID id, ServeEvent event) {
        if (get(id).isEmpty()) return;

        try (SqlSession session = MyBatisUtil.getSqlSession(false)) {
            WireMockJournalMapper sessionMapper = session.getMapper(WireMockJournalMapper.class);

            WireMockJournal journal = convertToJournal(event);
            WireMockJournalDetails details = convertToJournalDetails(event, journal.getId());

            sessionMapper.updateJournal(journal);
            sessionMapper.updateJournalDetails(details);
            session.commit();
        } catch (Exception e) {
            throw new RuntimeException("Failed to update ServeEvent (ID: " + id + ")", e);
        }
    }

    /**
     * 按ID删除日志：主表+详情表
     */
    @Override
    public void remove(UUID id) {
        try (SqlSession session = MyBatisUtil.getSqlSession(false)) {
            WireMockJournalMapper sessionMapper = session.getMapper(WireMockJournalMapper.class);

            sessionMapper.deleteJournalDetailsByJournalId(id.toString());
            sessionMapper.deleteJournalById(id.toString());
            session.commit();
        } catch (Exception e) {
            throw new RuntimeException("Failed to remove ServeEvent (ID: " + id + ")", e);
        }
    }

    /**
     * 清空所有日志：Truncate主表+详情表
     */
    @Override
    public void clear() {
        try (SqlSession session = MyBatisUtil.getSqlSession(false)) {
            WireMockJournalMapper sessionMapper = session.getMapper(WireMockJournalMapper.class);

            // 先清空详情表（避免外键冲突）
            sessionMapper.truncateJournalDetails();
            sessionMapper.truncateJournal();
            session.commit();
        } catch (Exception e) {
            throw new RuntimeException("Failed to clear all ServeEvents from DB", e);
        }
    }

    // ------------------------------
    // 辅助方法：实体转换（ServeEvent ↔ 数据库实体）
    // ------------------------------

    /**
     * ServeEvent → WireMockJournal（主表实体）
     */
    private WireMockJournal convertToJournal(ServeEvent event) {
        WireMockJournal journal = new WireMockJournal();
        LoggedRequest request = event.getRequest();
        LoggedResponse response = event.getResponse();
        Timing timing = event.getTiming();

        // 1. 核心字段（主表）
        journal.setId(event.getId().toString());
        journal.setRequestId(request != null ? request.getId().toString() : null);
        journal.setScheme(request != null ? request.getScheme() : null);
        journal.setHost(request != null ? request.getHost() : null);
        journal.setPort(request != null ? request.getPort() : -1);
        journal.setUrl(request != null ? request.getUrl() : null);
        journal.setAbsoluteUrl(request != null ? request.getAbsoluteUrl() : null);
        journal.setMethod(request != null ? request.getMethod().getName() : null);
        journal.setClientIp(request != null ? request.getClientIp() : null);
        journal.setProtocol(request != null ? request.getProtocol() : null);
        journal.setIsBrowserProxyRequest(request != null && request.isBrowserProxyRequest());
        journal.setLoggedDate(new Date()); // 日志生成时间（替代Timing.getStartedAt()）
        journal.setWasMatched(event.getResponseDefinition() != null && event.getResponseDefinition().wasConfigured());
        journal.setResponseStatus(response != null ? response.getStatus() : null);
        journal.setStubMappingId(event.getStubMapping() != null ? event.getStubMapping().getId().toString() : null);
        journal.setCreated_at(new Date());

        // 2. Timing相关字段（无getStartedAt()，用现有字段）
        journal.setTimingProcessTime(timing != null ? timing.getProcessTime() : null);
        journal.setTimingResponseSendTime(timing != null ? timing.getResponseSendTime() : null);
        journal.setTimingAddedTime(timing != null ? timing.getAddedDelay() : null); // 替代getAddedTime()

        return journal;
    }

    /**
     * ServeEvent → WireMockJournalDetails（详情表实体）
     */
    private WireMockJournalDetails convertToJournalDetails(ServeEvent event, String journalId) {
        WireMockJournalDetails details = new WireMockJournalDetails();
        LoggedRequest request = event.getRequest();
        LoggedResponse response = event.getResponse();
        ResponseDefinition responseDef = event.getResponseDefinition();

        try {
            details.setJournalId(journalId);

            // 3. 请求相关复杂字段（JSON序列化）
            if (request != null) {
                //  headers（HttpHeaders）
                details.setHeaders(objectMapper.writeValueAsString(request.getHeaders()));
                //  cookies（Map<String, Cookie>，无Cookies类）
                details.setCookies(objectMapper.writeValueAsString(request.getCookies()));
                //  queryParams（Map<String, QueryParameter>）
                details.setQueryParams(objectMapper.writeValueAsString(request.getQueryParams()));
                //  formParams（Map<String, FormParameter>，无FormParams类）
                details.setFormParams(objectMapper.writeValueAsString(request.formParameters()));
                //  pathParams（PathParams → Map）
                details.setPathParams(objectMapper.writeValueAsString(request.getPathParameters()));
                //  body与bodyAsBase64
                details.setBody(request.getBodyAsString());
                // getBodyAsBase64()返回String，直接赋值（无orElse()）
                String bodyBase64 = request.getBodyAsBase64();
                details.setBodyAsBase64(bodyBase64 != null ? bodyBase64 : Encoding.encodeBase64(request.getBody()));
                //  multiparts（Collection<Part>）
                List<Request.Part> partList = new ArrayList<>(request.getParts());
                details.setMultiparts(objectMapper.writeValueAsString(partList));
            }

            // 4. 响应相关复杂字段（无getInitialDelay()，从ResponseDefinition获取）
            if (response != null) {
                details.setResponseHeaders(objectMapper.writeValueAsString(response.getHeaders()));
                details.setResponseBody(response.getBodyAsString());
                // 响应Base64（无orElse()）
                String respBase64 = response.getBodyAsBase64();
                details.setResponseBodyAsBase64(respBase64 != null ? respBase64 : Encoding.encodeBase64(response.getBody()));
                // 响应延迟（从ResponseDefinition获取，替代getInitialDelay()）
                details.setResponseInitialDelay(responseDef != null ? responseDef.getFixedDelayMilliseconds() : null);
            }

            // 5. 子事件（SubEvent）
            details.setSubEvents(objectMapper.writeValueAsString(event.getSubEvents()));

        } catch (Exception e) {
            throw new RuntimeException("Failed to serialize JournalDetails (ID: " + journalId + ")", e);
        }
        return details;
    }

    /**
     * 数据库实体（主表+详情表）→ ServeEvent
     */
    private ServeEvent convertToServeEvent(WireMockJournal journal, WireMockJournalDetails details) {
        if (journal == null || details == null) return null;

        try {
            // 1. 构建 LoggedRequest（无builder，用Request代理+createFrom()）
            Request requestProxy = buildRequestProxy(journal, details);
            LoggedRequest loggedRequest = LoggedRequest.createFrom(requestProxy);

            // 2. 构建 LoggedResponse
            LoggedResponse loggedResponse = buildLoggedResponse(journal,details);

            // 3. 构建 Timing
            Timing timing = buildTiming(journal);

            // 4. 构建 SubEvents
            Queue<SubEvent> subEvents = buildSubEvents(details);

            // 5. 构建 StubMapping（仅含ID，避免冗余）
            StubMapping stubMapping = buildStubMapping(journal);

            // 6. 构建 ResponseDefinition
            ResponseDefinition responseDef = buildResponseDefinition(journal, details);

            // 7. 最终构建 ServeEvent
            return new ServeEvent(
                    UUID.fromString(journal.getId()),          // 1. ID
                    loggedRequest,                             // 2. LoggedRequest
                    stubMapping,                               // 3. StubMapping
                    responseDef,                               // 4. ResponseDefinition
                    loggedResponse,                            // 5. LoggedResponse
                    false,
                    timing,                                    // 6. Timing（正确位置）
                    new ConcurrentLinkedQueue<>(subEvents)    // 7. SubEvent队列（正确位置）
            );

        } catch (Exception e) {
            throw new RuntimeException("Failed to deserialize to ServeEvent (ID: " + journal.getId() + ")", e);
        }
    }

    // ------------------------------
    // 细分辅助方法：构建WireMock核心对象
    // ------------------------------

    /**
     * 构建 Request 代理（用于创建 LoggedRequest）
     */
    private Request buildRequestProxy(WireMockJournal journal, WireMockJournalDetails details) throws Exception {
        return new Request() {
            @Override
            public UUID getId() {
                return UUID.fromString(journal.getRequestId());
            }

            @Override
            public String getScheme() {
                return journal.getScheme();
            }

            @Override
            public String getHost() {
                return journal.getHost();
            }

            @Override
            public int getPort() {
                return journal.getPort() != null ? journal.getPort() : -1;
            }

            @Override
            public String getUrl() {
                return journal.getUrl();
            }

            @Override
            public String getAbsoluteUrl() {
                return journal.getAbsoluteUrl();
            }

            @Override
            public RequestMethod getMethod() {
                // 用RequestMethod替代HttpMethod
                return  RequestMethod.fromString(journal.getMethod());
            }

            @Override
            public String getClientIp() {
                return journal.getClientIp();
            }

            // 1. 修复getHeaders()：转为RuntimeException，无需声明
            @Override
            public HttpHeaders getHeaders() {
                try {
                    return objectMapper.readValue(details.getHeaders(), HttpHeaders.class);
                } catch (JsonProcessingException e) {
                    // 转为RuntimeException，附加日志上下文（如日志ID），便于排查
                    throw new RuntimeException(
                            "Failed to deserialize request headers (Journal ID: " + journal.getId() + ")",
                            e
                    );
                }
            }
            @Override
            public Map<String, Cookie> getCookies() {
                // 反序列化Map<String, Cookie>（无Cookies类）
                try {
                    return objectMapper.readValue(
                            details.getCookies(),
                            new TypeReference<Map<String, Cookie>>() {}
                    );
                } catch (JsonProcessingException e) {
                    throw new RuntimeException(
                            "Failed to deserialize request cookies (Journal ID: " + journal.getId() + ")",
                            e
                    );
                }
            }

            @Override
            public PathParams getPathParameters(){
                try {
                    Map<String, String> pathMap = objectMapper.readValue(
                            details.getPathParams(),
                            new TypeReference<Map<String, String>>() {}
                    );
                    PathParams pathParams = PathParams.empty();
                    pathParams.putAll(pathMap);
                    return pathParams;
                } catch (JsonProcessingException e) {
                    throw new RuntimeException(
                            "Failed to deserialize path parameters (Journal ID: " + journal.getId() + ")",
                            e
                    );
                }
            }

            @Override
            public byte[] getBody() {
                String body = details.getBody();
                return body != null ? body.getBytes(StandardCharsets.UTF_8) : new byte[0];
            }

            @Override
            public boolean isBrowserProxyRequest() {
                return journal.getIsBrowserProxyRequest() != null && journal.getIsBrowserProxyRequest();
            }

            @Override
            public Optional<Request> getOriginalRequest() {
                return Optional.empty();
            }

            @Override
            public String getProtocol() {
                return journal.getProtocol();
            }

            @Override
            public Map<String, FormParameter> formParameters() {
                try {
                    return objectMapper.readValue(
                            details.getFormParams(),
                            new TypeReference<Map<String, FormParameter>>() {}
                    );
                } catch (JsonProcessingException e) {
                    // 明确捕获反序列化异常，附加上下文，且不吞异常（抛RuntimeException）
                    throw new RuntimeException(
                            "Failed to deserialize form parameters (Journal ID: " + journal.getId() + ")",
                            e
                    );
                } catch (Exception e) {
                    // 其他异常（如类型转换）也需带上下文
                    throw new RuntimeException(
                            "Unexpected error when getting form parameters (Journal ID: " + journal.getId() + ")",
                            e
                    );
                }
            }

            @Override
            public Collection<Part> getParts() {
                try {
                    String multipartsJson = details.getMultiparts();
                    // 1. 处理 null/空字符串：返回空列表
                    if (multipartsJson == null || multipartsJson.trim().isEmpty()) {
                        return Collections.emptyList();
                    }

                    // 2. 兼容旧数据：若为 JSON 对象（{}），返回空列表
                    String trimmedJson = multipartsJson.trim();
                    if (trimmedJson.startsWith("{")) {
                        return Collections.emptyList();
                    }

                    // 3. 正常数组格式：反序列化为 List<Part>
                    return objectMapper.readValue(
                            multipartsJson,
                            new TypeReference<List<Part>>() {}
                    );
                } catch (JsonProcessingException e) {
                    throw new RuntimeException(
                            "Failed to deserialize multipart parts (Journal ID: " + journal.getId() + ")",
                            e
                    );
                } catch (Exception e) {
                    throw new RuntimeException(
                            "Unexpected error when getting multipart parts (Journal ID: " + journal.getId() + ")",
                            e
                    );
                }
            }

            // ------------------------------
            // Request接口默认实现（无需修改）
            // ------------------------------
            @Override
            public String getHeader(String key)  {
                return getHeaders().getHeader(key).firstValue();
            }

            @Override
            public HttpHeader header(String key){
                return getHeaders().getHeader(key);
            }

            @Override
            public ContentTypeHeader contentTypeHeader()  {
                return getHeaders().getContentTypeHeader();
            }

            @Override
            public boolean containsHeader(String key){
                return getHeaders().getHeader(key).isPresent();
            }

            @Override
            public QueryParameter queryParameter(String key) {
                Map<String, QueryParameter> queryParams = getQueryParams();
                return queryParams.getOrDefault(key, QueryParameter.absent(key));
            }

            @Override
            public FormParameter formParameter(String key) {
                return formParameters().getOrDefault(key, FormParameter.absent(key));
            }

            @Override
            public String getBodyAsString() {
                return new String(getBody(), StandardCharsets.UTF_8);
            }

            @Override
            public String getBodyAsBase64() {
                String base64 = details.getBodyAsBase64();
                return base64 != null ? base64 : Encoding.encodeBase64(getBody());
            }

            @Override
            public Set<String> getAllHeaderKeys(){
                return getHeaders().keys();
            }

            @Override
            public boolean isMultipart() {
                return !getParts().isEmpty();
            }

            @Override
            public Part getPart(String name) {
                return getParts().stream()
                        .filter(part -> name.equals(part.getName()))
                        .findFirst()
                        .orElse(null);
            }

            // 辅助：获取查询参数（从详情表反序列化）
            private Map<String, QueryParameter> getQueryParams() {
                try {
                    return objectMapper.readValue(
                            details.getQueryParams(),
                            new TypeReference<Map<String, QueryParameter>>() {}
                    );
                } catch (Exception e) {
                    return Collections.emptyMap();
                }
            }
        };
    }

    /**
     * 构建 LoggedResponse
     */
    private LoggedResponse buildLoggedResponse(WireMockJournal journal, WireMockJournalDetails details){
        // 1. 反序列化响应头：处理 null 值，返回空 HttpHeaders
        HttpHeaders respHeaders;
        try {
            String responseHeadersJson = details.getResponseHeaders();
            if (responseHeadersJson == null || responseHeadersJson.trim().isEmpty()) {
                // 若响应头为 null 或空字符串，返回空的 HttpHeaders（避免反序列化报错）
                respHeaders = HttpHeaders.noHeaders();
            } else {
                // 正常反序列化
                respHeaders = objectMapper.readValue(
                        responseHeadersJson,
                        HttpHeaders.class
                );
            }
        } catch (JsonProcessingException e) {
            throw new RuntimeException(
                    "Failed to deserialize response headers (Journal ID: " + journal.getId() + ")",
                    e
            );
        }

        // 2. 响应体（byte[]）：处理 null 值
        String responseBodyStr = details.getResponseBody();
        byte[] respBody = responseBodyStr != null
                ? responseBodyStr.getBytes(StandardCharsets.UTF_8)
                : new byte[0];

        // 3. 响应状态码（从主表journal获取，默认200）
        int status = journal.getResponseStatus() != null ? journal.getResponseStatus() : 200;

        // 4. 响应体转为Base64字符串（构造函数要求）
        String bodyAsBase64 = Encoding.encodeBase64(respBody);

        // 5. 构造LoggedResponse（参数完全匹配）
        return new LoggedResponse(
                status,                // 状态码
                respHeaders,           // 响应头（空或正常反序列化结果）
                bodyAsBase64,          // Base64响应体
                null,                  // 错误类型（无则传null）
                null                   // 忽略的body参数
        );
    }
    /**
     * 构建 Timing（无getStartedAt()，用主表字段）
     */
    private Timing buildTiming(WireMockJournal journal) {
        Timing timing = Timing.create();

        // 1. 处理 processTime
        if (journal.getTimingProcessTime() != null) {
            long processTime = journal.getTimingProcessTime();
            Stopwatch processStopwatch = createStopwatchWithMillis(processTime);
            timing.logProcessTime(processStopwatch);
        }

        // 2. 处理 responseSendTime
        if (journal.getTimingResponseSendTime() != null) {
            long responseTime = journal.getTimingResponseSendTime();
            Stopwatch responseStopwatch = createStopwatchWithMillis(responseTime);
            timing.logResponseSendTime(responseStopwatch);
        }

        // 3. 处理 addedTime（直接设置毫秒数，无需 Stopwatch）
        if (journal.getTimingAddedTime() != null) {
            timing.setAddedTime(journal.getTimingAddedTime());
        }

        return timing;
    }

    // 辅助方法：创建指定毫秒数的 Stopwatch
    private Stopwatch createStopwatchWithMillis(long millis) {
        Stopwatch stopwatch = Stopwatch.createUnstarted(); // 创建未启动的计时器
        try {
            // 反射获取 Stopwatch 内部存储时间的字段（elapsedNanos，long类型）
            Field elapsedNanosField = Stopwatch.class.getDeclaredField("elapsedNanos");
            elapsedNanosField.setAccessible(true); // 允许修改私有字段

            // 将毫秒转换为纳秒（Stopwatch 内部用纳秒存储）
            long elapsedNanos = TimeUnit.MILLISECONDS.toNanos(millis);
            elapsedNanosField.set(stopwatch, elapsedNanos); // 设置自定义时间
        } catch (NoSuchFieldException | IllegalAccessException e) {
            // 反射失败时的兜底（返回空计时器）
            throw new RuntimeException("Failed to create custom Stopwatch", e);
        }
        return stopwatch;
    }
    /**
     * 构建 SubEvents 队列
     */
    private Queue<SubEvent> buildSubEvents(WireMockJournalDetails details){
        if (details.getSubEvents() == null) return new ConcurrentLinkedQueue<>();

        List<SubEvent> subEventList = null;
        try {
            subEventList = objectMapper.readValue(
                    details.getSubEvents(),
                    new TypeReference<List<SubEvent>>() {}
            );
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        return new ConcurrentLinkedQueue<>(subEventList);
    }

    /**
     * 构建 StubMapping（仅含ID）
     */
    private StubMapping buildStubMapping(WireMockJournal journal) {
        if (journal.getStubMappingId() == null) return null;

        StubMapping stubMapping = new StubMapping();
        stubMapping.setId(UUID.fromString(journal.getStubMappingId()));
        return stubMapping;
    }

    /**
     * 构建 ResponseDefinition（含延迟配置）
     */
    private ResponseDefinition buildResponseDefinition(WireMockJournal journal, WireMockJournalDetails details){
        // 1. 从数据库获取实际响应状态码（主表 journal）
        int status = journal.getResponseStatus() != null ? journal.getResponseStatus() : 200;

        // 2. 从数据库获取响应头（详情表 details）
        HttpHeaders respHeaders = null;
        try {
            respHeaders = objectMapper.readValue(
                    details.getResponseHeaders(),
                    HttpHeaders.class
            );
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        Integer responseInitialDelay = details.getResponseInitialDelay();
        // 3. 构建 ResponseDefinition：使用数据库中的状态码
        return new ResponseDefinition(
                status,                          // 对应 .withStatus(status)
                null,                            // 状态消息（无需设置则传null）
                (byte[]) null,                   // body（无需设置则传null）
                null,                            // jsonBody（无需设置则传null）
                null,                            // base64Body（无需设置则传null）
                null,                            // bodyFileName（无需设置则传null）
                respHeaders,                     // 对应 .withHeaders(respHeaders)
                null,                            // additionalProxyRequestHeaders（默认null）
                null,                            // removeProxyRequestHeaders（默认null）
                details.getResponseInitialDelay(),// 对应 .withFixedDelayMilliseconds(...)
                null,                            // delayDistribution（默认null）
                null,                            // chunkedDribbleDelay（默认null）
                null,                            // proxyBaseUrl（默认null）
                null,                            // proxyUrlPrefixToRemove（默认null）
                null,                            // fault（默认null）
                Collections.emptyList(),         // transformers（默认空列表）
                Parameters.empty(),              // transformerParameters（默认空）
                true                             // wasConfigured（默认true）
        );
    }
}